<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Drag</title>
    <script src="../../../../../is-touch-device.js"></script>

    <style type="text/css">
        .draggable-div {
            position: absolute;
            background-color: gray;
            border: none;
            width: 100px;
            height: 100px;
            z-index: 2;
        }

        #draggable-div-1 {
            left: 0;
            top: 0;
        }

        #draggable-div-2 {
            left: 200px;
            top: 0;
        }

        #draggable-div-3 {
            left: 400px;
            top: 0;
        }

        .destination {
            position: absolute;
            background-color: red;
            border: none;
            width: 100px;
            height: 100px;
        }

        #destination-div {
            left: 0;
            top: 200px;
        }

        #destination-div-2 {
            left: 200px;
            top: 400px;
        }
    </style>
</head>
<body>
<div id="draggable-div-1" class="draggable-div"></div>
<div id="draggable-div-2" class="draggable-div"></div>
<div id="draggable-div-3" class="draggable-div"></div>

<div id="destination-div" class="destination"></div>
<div id="destination-div-2" class="destination"></div>

<input type="button" id="invisible" value="invisible-button" style="display: none;"/>


<!-- Init drag behavior -->
<script>
    (function () {
        const touchDevice = isTouchDevice();

        function getClientX (e) {
            return touchDevice ? e.touches[0].clientX : e.clientX;
        }

        function getClientY (e) {
            return touchDevice ? e.touches[0].clientY : e.clientY;
        }

        function initDraggable (element) {
            let cursorOffsetLeft = 0;
            let cursorOffsetTop  = 0;

            function onMouseMove (e) {
                element.style.left = getClientX(e) - cursorOffsetLeft + 'px';
                element.style.top  = getClientY(e) - cursorOffsetTop + 'px';
            }

            function onMouseDown (e) {
                const left = element.offsetLeft;
                const top  = element.offsetTop;

                element.style.opacity = 0.5;
                element.style.border  = '1px dotted black';

                cursorOffsetLeft = getClientX(e) - left;
                cursorOffsetTop  = getClientY(e) - top;

                document.addEventListener(touchDevice ? 'touchmove' : 'mousemove', onMouseMove, true);
                document.addEventListener(touchDevice ? 'touchend' : 'mouseup', onMouseUp, true);
            }

            function onMouseUp () {
                element.style.opacity = 1;
                element.style.border  = 'none';

                document.removeEventListener(touchDevice ? 'touchmove' : 'mousemove', onMouseMove, true);
                document.removeEventListener(touchDevice ? 'touchend' : 'mouseup', onMouseUp, true);
            }

            element.addEventListener(touchDevice ? 'touchstart' : 'mousedown', onMouseDown, true);
        }

        initDraggable(document.getElementById('draggable-div-1'));
        initDraggable(document.getElementById('draggable-div-2'));
        initDraggable(document.getElementById('draggable-div-3'));
    })();

</script>

<!-- Drag to offset test -->
<script>
    (function () {
        const touchDevice = isTouchDevice();

        const draggable1 = document.getElementById('draggable-div-1');
        const startPos   = { x: 0, y: 0 };
        const endPos     = { x: 0, y: 0 };

        let moveEventRaised = false;

        draggable1.addEventListener(touchDevice ? 'touchstart' : 'mousedown', function () {
            startPos.x = draggable1.offsetLeft;
            startPos.y = draggable1.offsetTop;
        });

        draggable1.addEventListener(touchDevice ? 'touchmove' : 'mousemove', function () {
            moveEventRaised = true;
        });

        draggable1.addEventListener(touchDevice ? 'touchend' : 'mouseup', function () {
            endPos.x = draggable1.offsetLeft;
            endPos.y = draggable1.offsetTop;

            if (moveEventRaised && endPos.x - startPos.x === 10 && endPos.y - startPos.y === 20)
                throw new Error('Drag to offset completed successfully');
            else {
                throw new Error([
                    'Drag was not completed successfully:',
                    'moveEventRaised: expected true but was ' + moveEventRaised + ';',
                    'left position offset: expected 10 but was ' + (endPos.x - startPos.x) + ';',
                    'top position offset: expected 10 but was ' + (endPos.y - startPos.y) + ';'
                ].join(' '));
            }
        });
    })();
</script>

<!-- Drag to element test -->
<script>
    (function () {
        const touchDevice = isTouchDevice();

        const draggable2  = document.getElementById('draggable-div-2');
        const destination = document.getElementById('destination-div');
        const startPos    = { x: 0, y: 0 };
        const endPos      = { x: 0, y: 0 };

        let moveEventRaised = false;

        const destinationDivPos    = { x: destination.offsetLeft, y: destination.offsetTop };
        const destinationDivCenter = { x: destination.offsetWidth / 2, y: destination.offsetHeight / 2 };

        const destinationPos = {
            x: destinationDivPos.x + destinationDivCenter.x,
            y: destinationDivPos.y + destinationDivCenter.y
        };

        draggable2.addEventListener(touchDevice ? 'touchstart' : 'mousedown', function () {
            startPos.x = draggable2.offsetLeft;
            startPos.y = draggable2.offsetTop;
        });

        draggable2.addEventListener(touchDevice ? 'touchmove' : 'mousemove', function () {
            moveEventRaised = true;
        });

        draggable2.addEventListener(touchDevice ? 'touchend' : 'mouseup', function () {
            endPos.x = draggable2.offsetLeft;
            endPos.y = draggable2.offsetTop;

            const expectedPos = {
                x: destinationPos.x - 10,
                y: destinationPos.y - 10
            };

            if (moveEventRaised && endPos.x === expectedPos.x && endPos.y === expectedPos.y)
                throw new Error('Drag to element completed successfully');
            else {
                throw new Error([
                    'Drag was not completed successfully:',
                    'moveEventRaised: expected true but was ' + moveEventRaised + ';',
                    'left position: expected ' + expectedPos.x + ' but was ' + endPos.x + ';',
                    'top position: expected ' + expectedPos.y + ' but was ' + endPos.y + ';'
                ].join(' '));
            }
        });
    })();
</script>
</body>
</html>
